﻿
namespace HSS.Xaml.UI.Controls
{
	#region Using Directives
	using System;
	using System.Collections.Generic;
	using System.Windows;
	using System.Windows.Controls;
	using HSS.ComponentModel;
	#endregion

	#region ComboBoxEditorBase
	/// <summary>
	/// An abstract editor for any Type Editors that make use of a DropDownList
	/// </summary>
	public abstract class ComboBoxEditorBase : PropertyGridEditor
	{
		#region Constructors
		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="descriptor">The <see cref="HSSPropertyDescriptor"/> to be edited.</param>
		protected ComboBoxEditorBase(HSSPropertyDescriptor descriptor)
			: base(descriptor)
		{
		}
		#endregion

		#region Properties
		/// <summary>
		/// The current Control (inline editor)
		/// </summary>
		protected ComboBox Control
		{
			get
			{
				return (ComboBox)base.InlineEditControl;
			}
		}
		#endregion

		#region Overrides
		/// <summary>
		/// Creates the Inline Editor control.
		/// </summary>
		/// <returns>The control as a FrameworkElement.</returns>
		protected override FrameworkElement CreateInlineEditControl()
		{
			var box = new ComboBox();
			box.ItemTemplate = ControlUtil.CreateDataTemplate(typeof(TextBlock), "ObjectDisplay");
			return box;
		}
		/// <summary>
		/// Initialize the Inline Editor Control.
		/// </summary>
		protected override void InitializeInlineEditControl()
		{
			base.InitializeInlineEditControl();
			var listItems = this.GetListItems();
			this.LoadItems(listItems);
			this.SyncValue(this.Object);
		}
		/// <summary>
		/// Updates the editor with the new value.
		/// </summary>
		/// <param name="newValue">The new value.</param>
		protected override void UpdateInlineEditControl(object newValue)
		{
			this.SyncValue(newValue);
		}
		/// <summary>
		/// Gets the current value held by the control.
		/// </summary>
		/// <returns>The object.</returns>
		protected override object GetControlValue()
		{
			if (null == this.Control.SelectedItem)
				return null;
			return ((ComboBoxItemObject)this.Control.SelectedItem).ObjectValue;
		}
		/// <summary>
		/// Begin the editing process.
		/// </summary>
		protected override void OnBeginEdit()
		{
			base.OnBeginEdit();
			this.Control.DropDownClosed += new EventHandler(this.Control_DropDownClosed);
		}
		/// <summary>
		/// End the editing process.
		/// </summary>
		protected override void OnEndEdit()
		{
			base.OnEndEdit();
			this.Control.DropDownClosed -= new EventHandler(this.Control_DropDownClosed);
		}
		#endregion

		#region Methods
		/// <summary>
		/// Sync's the provided object value to an item in the ComboBox if one
		/// exists.
		/// </summary>
		/// <param name="value">The value to sync to</param>
		protected void SyncValue(object value)
		{
			for (int i = 0; i < this.Control.Items.Count; i++)
			{
				object val = ((ComboBoxItemObject)this.Control.Items[i]).ObjectValue;
				if (this.SyncValueEquals(val, value))
				{
					this.Control.SelectedIndex = i;
					break;
				}
			}
		}
		/// <summary>
		/// Compares the value1 against value2 for equality
		/// </summary>
		/// <param name="value1">The value from the list</param>
		/// <param name="value2">The value to edit</param>
		/// <returns>True if the values are equal</returns>
		protected virtual bool SyncValueEquals(object value1, object value2)
		{
			Guard.ArgumentNotNull(value1, "value1");
			return value1.Equals(value2);
		}
		/// <summary>
		/// Load the items for the ComboBox
		/// </summary>
		/// <param name="items">IEnumerable list of Objects</param>
		protected virtual void LoadItems(IEnumerable<object> items)
		{
			Guard.ArgumentNotNull(items, "items");
			var Items = new List<ComboBoxItemObject>();
			foreach (var item in items)
				Items.Add(new ComboBoxItemObject(item.ToString(), item));
			this.Control.ItemsSource = Items;
		}
		#endregion

		#region Event Handlers
		void Control_DropDownClosed(object sender, EventArgs e)
		{
			this.EndEdit();
		}
		#endregion

		#region Abstract
		/// <summary>
		/// Retrieve the list of available objects for the ComboBox
		/// </summary>
		/// <returns></returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
		protected abstract IEnumerable<object> GetListItems();
		#endregion
	}
	#endregion
}
